package org.helios.gwt.remote.sample.client;

import java.util.HashMap;
import java.util.Map;

import org.helios.gwt.remote.client.Exporter;
import org.helios.gwt.remote.client.Importer;
import org.helios.gwt.remote.sample.client.shared.PortalHandle;
import org.helios.gwt.remote.sample.client.shared.PortletHandle;
import org.helios.gwt.remote.sample.client.shared.PortletModuleHandle;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.dom.client.ScriptElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalSplitPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class Portal extends Composite 
{
	public Portal()
	{
		initWidget(createWidget());
	}
	
	private Widget createWidget()
	{
		HorizontalSplitPanel panel = new HorizontalSplitPanel();
		panel.add(vertical = new VerticalPanel());
		
		Panel controlPanel = new VerticalPanel();
		controlPanel.add(new Label("Agregar module"));
		final TextBox textModule = new TextBox();
		textModule.setText("org.helios.gwt.remote.sample.Portlet/org.helios.gwt.remote.sample.Portlet.nocache.js");
		controlPanel.add(textModule);
		controlPanel.add(new Button("agregar!", new ClickHandler() {
			public void onClick(ClickEvent event) {
				String module = textModule.getText();
				addModule(module);
			}
		}));
		controlPanel.add(new Button("agregar portlet1", new ClickHandler() {
			public void onClick(ClickEvent event) {
				String module = modules.keySet().iterator().next();
				addPortlet(module, "portlet1");
			}
		}));
		
		controlPanel.add(labelModules = new Label("Módulos:"));
		
		panel.add(controlPanel);
		
		registerGlobalEntry();
		
		return panel;
	}

	private Label labelModules;
	
	private void registerGlobalEntry()
	{
		GlobalEntryExporter exporter = GWT.create(GlobalEntryExporter.class);
		registerGlobalEntry(exporter.export(new PortalHandleImpl()));
	}
	
	private class PortalHandleImpl implements PortalHandle
	{
		public void registerPortletModule(PortletModuleHandle module)
		{
			final String moduleId = module.getId();
			modules.put(moduleId, module);
			Panel panel = (Panel) labelModules.getParent();
			panel.add(new Label("** Módulo: " + module.getId()));
			for (final String portletId: module.getPortletIds())
			{
				Label label = new Label("- portlet: " + portletId);
				label.addClickHandler(new ClickHandler() {
					public void onClick(ClickEvent event) {
						addPortlet(moduleId, portletId);
					}
				});
				panel.add(label);
			}
		}
	}
	
	private Map<String, PortletModuleHandle> modules = new HashMap<String, PortletModuleHandle>();
	
	interface GlobalEntryExporter extends Exporter<PortalHandle> {}
	
	private native void registerGlobalEntry(JavaScriptObject globalEntry) /*-{
		$wnd.__portal_global_entry = globalEntry;
	}-*/;
	
	private void addModule(String moduleUrl)
	{
		// necesita un marker y el docwrite no lo hace bien
		// se lo hago yo
		ScriptElement marker = this.getElement().getOwnerDocument().createScriptElement();
		marker.setId("__gwt_marker_org.helios.gwt.remote.sample.Portlet");
		this.getElement().getOwnerDocument().getBody().appendChild(marker);
		
		final ScriptElement script = this.getElement().getOwnerDocument().createScriptElement();
		script.setType("text/javascript");
		script.setSrc(moduleUrl);
		
		//addHandler(script, "com_dia_nexdia_portal_Portlet", "com.dia.nexdia.portal.Portlet");
		Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
			
			public boolean execute() {
				return !addHandler(script, "org_helios_gwt_remote_sample_Portlet", "org.helios.gwt.remote.sample.Portlet");
			}
			
			private native boolean addHandler(ScriptElement e, String moduleUnderscore, String moduleName) /*-{
				var modFunc = $wnd[moduleUnderscore];
				if (modFunc)
					modFunc.onInjectionDone(moduleName);
				return modFunc;
			}-*/;
		}, 100);
		
		this.getElement().getOwnerDocument().getBody().insertBefore(script, marker);
	}
	
	private native void addHandler(ScriptElement e, String moduleUnderscore, String moduleName) /*-{
		var loadit = function() {
			$wnd[moduleUnderscore].onInjectionDone(moduleName);
		};
		e.onload = loadit;
		e.onreadystatechange= function () {
      		if (this.readyState == 'complete') loadit();
   		}
	}-*/;

	private void addPortlet(String moduleId, String portletId)
	{
		PortletModuleHandle moduleHandle = modules.get(moduleId);
		String instanceId = "" + counter;
		final PortletBox box = new PortletBox(instanceId);
		box.addCloseHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				close(box);
			}
		});
		vertical.add(box);
		PortletHandle handle = moduleHandle.placePortlet(portletId, box.getWhereId(), instanceId);
		box.setHandle(handle);
		counter++;
	}

	private void close(PortletBox box)
	{
		box.getHandle().removeFromParent();
		box.removeFromParent();
	}
	
	interface PortletHandleImporter extends Importer<PortletHandle> {}
	
	private VerticalPanel vertical;
	private int counter;
}
